/*
 * ArcEmu MMORPG Server
 * Copyright (C) 2005-2007 Ascent Team <http://www.ascentemu.com/>
 * Copyright (C) 2008 <http://www.ArcEmu.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef __SPELL_H
#define __SPELL_H

#include "SpellFailure.h"
#include "StdAfx.h"

class WorldSession;
class Unit;
class DynamicObj;
class Player;
class Item;
class Group;
class Aura;
/* Spell Ranges:(for 1.10.2)
Range ID|Range|Description
1       0-0     Self Only
2       0-5     Combat Range
3       0-20    Short Range
4       0-30    Medium Range
5       0-40    Long Range
6       0-100   Vision Range
7       0-10    Very Short Range
8       10-20   Short Range
9       10-30   Medium Range
10      10-40   Long Range
11      0-15    Shorter Range
12      0-5     Interact Range
13      0-50000 Anywhere
14      0-60    Extra Long Range
34      0-25    Medium-Short Range
35      0-35    Medium-Long Range
36      0-45    Longer Range
37      0-50    Extended Range
38      10-25   Extra Medium Range
54      5-30    Geoff Monster Shoot
74      8-30    Ranged Weapon
94      8-40    Sting
95      8-25    Charge
96      0-2     Trap
114     8-35    Hunter Range Hunter
134     0-80    Tower 80 Tower
135     0-100   Tower 100 Tower
*/

/*FLAT PCT
0    x    x
1    x    x
2    x    x
3         x
4    x
5    x    x
6    x    x
7    x =  x//both add % to crit
8    x    x
9         x
10   x    x
11   x    x
12   x
13    
14   x    x
15        x
16   x    
17   x
18   x    x
19   x
20        x
21    
22   x    x
23   x(enslave dem)
24    
25
26   x(obsolete)
27        x
*/

//wooohooo, there are 19 spells that actually require to add a proccounter for these 
//first spell catched is "presence of mind"
//an ugly solution would be to add a proc flag to remove aura on event it should expire (like attack or cast) but that is only if count=1
enum SPELL_MODIFIER_TYPE
{
    SMT_DAMAGE_DONE         =0,// increases the damage done by spell by x% dmg (flat as x dmg)
    SMT_DURATION            =1,// spell    duration increase // GOOD
    //hmm shaman spirit weapon clearly states that this should be parry chance
    SMT_THREAT_REDUCED      =2,// reduces threat generated by this spell by x% // GOOD but need more work
    SMT_ATTACK_POWER_AND_DMG_BONUS=3,// attacker power bonus for ability +x% // Seal of crusader also takes this as dmg bonus + power bonus 
    SMT_CHARGES             =4,// block additional attack // GOOD and need work //Not used in 2.1.1 ?
    SMT_RANGE               =5,// spell range bonus // GOOD
    SMT_RADIUS              =6,// spell radius bonus // GOOD
    SMT_CRITICAL            =7,// critical chance bonus // GOOD //only 1 example in 2.1.1
    SMT_MISC_EFFECT         =8,// dummy effect // needs work is not only pets Hp but effect of spells to
    SMT_NONINTERRUPT        =9,// x% chance not to be interrupted by received damage (no flat)
    SMT_CAST_TIME           =10,// cast time decrease // GOOD
    SMT_COOLDOWN_DECREASE   =11,// cooldown decrease <-probably fully handled by client // GOOD
    SMT_EFFECT              = 12,//used by shaman elemental weapons and another spell
//    SMT_SPEED             =12,// movement speed, while given spell is active(flat is %) // TODO CHECK! ok this is not speed and is used with 23 misc to sometimes so is odd
    // 13 dont exist spells with it
    SMT_COST                =14,// mana/energy/rage cost reduction // GOOD
    SMT_CRITICAL_DAMAGE     =15,// increases critical strike damage bonus (no flat)
    SMT_HITCHANCE           =16,// enemy resist chance decrease (flat as %) // GOOD need work
    SMT_ADDITIONAL_TARGET   =17,// Your Healing Wave will now jump to additional nearby targets. Each jump reduces the effectiveness of the heal by 80% // GOOD
    SMT_TRIGGER             =18,// adds/increases chance to trigger some spell for example increase chance to apply poisons or entaglin // GOOD need work
    SMT_TIME                =19,// delay for nova, redirection time bonus for totem,maybe smth else // GOOD need work
    SMT_JUMP_REDUCE         =20,// Increases the amount healed by Chain Heal to targets beyond the first by x%. (no flat)
    //SMT_CAST_TIME2        =21,// this one looks like cast time...
	//!!! most spells have both SMT_DAMAGE_DONE and this value. Be carefull case there is no need to apply both !
    SMT_SPELL_VALUE_PCT		=22,// damage done by ability by x% : SELECT id,name,description FROM dbc_spell where (EffectApplyAuraName_1=108 and EffectMiscValue_1=22) or (EffectApplyAuraName_2=108 and EffectMiscValue_2=22) or (EffectApplyAuraName_3=108 and EffectMiscValue_3=22)  its DoT actually
    SMT_UNKNOWN23           =23,// this seems to be some scripted effect. From 8 spells not even 1 has description what it does
    SMT_PENALTY             =24,// This is a modifer for the amount of +spell damage applied to the spell group from spell bonuses
    // 25 dont exist spells with it
    // 26 is obsolete stuff
    SMT_EFFECT_BONUS        =27,// mana lost cost per point of damage taken for mana shield,Health or Mana gained from Drain Life and Drain Mana increased by x%.
    SMT_RESIST_DISPEL       =28,// TODO NEEDS WORK :D
};


static void SM_FFValue( int32* m, float* v, uint32* group )
{
    if( m == 0 )
		return;

    uint32 intbit = 0, groupnum = 0;
	for(uint32 bit = 0; bit < SPELL_GROUPS; ++bit, ++intbit)
	{
		if(intbit == 32)
		{
			++groupnum;
			intbit = 0;
		}
		if( ( 1 << intbit ) & group[groupnum] )
			(*v) += m[bit];
	}
}

static void SM_FIValue( int32* m, int32* v, uint32* group )
{
    if( m == 0 )
		return;

	uint32 intbit = 0, groupnum = 0;
	for(uint32 bit = 0; bit < SPELL_GROUPS; ++bit, ++intbit)
	{
		if(intbit == 32)
		{
			++groupnum;
			intbit = 0;
		}
		if( ( 1 << intbit ) & group[groupnum] )
			(*v) += m[bit];
	}
}

static void SM_PIValue( int32* m, int32* v, uint32* group )
{
    if( m == 0 )
		return;

	uint32 intbit = 0, groupnum = 0;
	for(uint32 bit = 0; bit < SPELL_GROUPS; ++bit, ++intbit)
	{
		if(intbit == 32)
		{
			++groupnum;
			intbit = 0;
		}
		if( ( 1 << intbit ) & group[groupnum] )
			(*v) += ( (*v) * m[bit] ) / 100;
	}
}

static void SM_PFValue( int32* m, float* v, uint32* group )
{
    if( m == 0 )
		return;
    
	uint32 intbit = 0, groupnum = 0;
	for(uint32 bit = 0; bit < SPELL_GROUPS; ++bit, ++intbit)
	{
		if(intbit == 32)
		{
			++groupnum;
			intbit = 0;
		}
		if( ( 1 << intbit ) & group[groupnum] )
			(*v) += ( (*v) * m[bit] ) / 100.0f;
	}
}

enum SPELL_INFRONT_STATUS
{
	SPELL_INFRONT_STATUS_REQUIRE_SKIPCHECK	= 0,
	SPELL_INFRONT_STATUS_REQUIRE_INFRONT	= 1,
	SPELL_INFRONT_STATUS_REQUIRE_INBACK		= 2,
};

//bool IsBeneficSpell(SpellEntry *sp);
//AI_SpellTargetType RecommandAISpellTargetType(SpellEntry *sp);

enum SPELL_DMG_TYPE // SPELL_ENTRY_Spell_Dmg_Type
{
	SPELL_DMG_TYPE_NONE   = 0,
	SPELL_DMG_TYPE_MAGIC  = 1,
	SPELL_DMG_TYPE_MELEE  = 2,
	SPELL_DMG_TYPE_RANGED = 3
};

enum SPELL_RUNE_TYPES
{
	RUNE_BLOOD		= 0,
	RUNE_UNHOLY		= 1,
	RUNE_FROST		= 2,
	RUNE_DEATH		= 3,
};

// value's for SendSpellLog
enum SPELL_LOG
{
    SPELL_LOG_NONE,
    SPELL_LOG_MISS,
    SPELL_LOG_RESIST,
    SPELL_LOG_DODGE,
    SPELL_LOG_PARRY,
    SPELL_LOG_BLOCK,
    SPELL_LOG_EVADE,
    SPELL_LOG_IMMUNE,
    SPELL_LOG_IMMUNE2,
    SPELL_LOG_DEFLECT,
    SPELL_LOG_ABSORB,
    SPELL_LOG_REFLECT
};

enum SpellCastTargetFlags
{
    TARGET_FLAG_SELF                = 0x0000, // they are checked in following order
    TARGET_FLAG_UNK1                = 0x0001,
    TARGET_FLAG_UNIT                = 0x0002,
    TARGET_FLAG_UNK2                = 0x0004,
    TARGET_FLAG_UNK3                = 0x0008,
    TARGET_FLAG_ITEM                = 0x0010,
    TARGET_FLAG_SOURCE_LOCATION     = 0x0020,
    TARGET_FLAG_DEST_LOCATION       = 0x0040,
    TARGET_FLAG_UNK6                = 0x0080,
    TARGET_FLAG_UNK7                = 0x0100,
    TARGET_FLAG_CORPSE              = 0x0200,
    TARGET_FLAG_UNK8                = 0x0400,
    TARGET_FLAG_OBJECT              = 0x0800,
    TARGET_FLAG_TRADE_ITEM          = 0x1000,
    TARGET_FLAG_STRING              = 0x2000,
    TARGET_FLAG_UNK9                = 0x4000,
    TARGET_FLAG_CORPSE2             = 0x8000
};
#ifndef NEW_PROCFLAGS 
enum procFlags
{
	PROC_NULL							= 0x0,
	PROC_ON_ANY_HOSTILE_ACTION			= 0x1,
	PROC_ON_GAIN_EXPIERIENCE			= 0x2,
	PROC_ON_MELEE_ATTACK				= 0x4,
	PROC_ON_CRIT_HIT_VICTIM				= 0x8,
	PROC_ON_CAST_SPELL					= 0x10,
	PROC_ON_PHYSICAL_ATTACK_VICTIM		= 0x20,
	PROC_ON_RANGED_ATTACK				= 0x40,
	PROC_ON_RANGED_CRIT_ATTACK			= 0x80,
	PROC_ON_PHYSICAL_ATTACK				= 0x100,
	PROC_ON_MELEE_ATTACK_VICTIM			= 0x200,
	PROC_ON_SPELL_HIT					= 0x400,
	PROC_ON_RANGED_CRIT_ATTACK_VICTIM	= 0x800,
	PROC_ON_CRIT_ATTACK					= 0x1000,
	PROC_ON_RANGED_ATTACK_VICTIM		= 0x2000,
	PROC_ON_PRE_DISPELL_AURA_VICTIM		= 0x4000,
	PROC_ON_SPELL_LAND_VICTIM			= 0x8000,
	PROC_ON_CAST_SPECIFIC_SPELL			= 0x10000,
	PROC_ON_SPELL_HIT_VICTIM			= 0x20000,
	PROC_ON_SPELL_CRIT_HIT_VICTIM		= 0x40000,
	PROC_ON_TARGET_DIE					= 0x80000,
	PROC_ON_ANY_DAMAGE_VICTIM			= 0x100000,
	PROC_ON_TRAP_TRIGGER				= 0x200000, //triggers on trap activation)
	PROC_ON_AUTO_SHOT_HIT				= 0x400000,
	PROC_ON_ABSORB						= 0x800000,
	PROC_ON_RESIST_VICTIM				= 0x1000000,
	PROC_ON_DODGE_VICTIM				= 0x2000000,
	PROC_ON_DIE							= 0x4000000,
	PROC_REMOVEONUSE					= 0x8000000,//remove prochcharge only when it is used
	PROC_MISC							= 0x10000000,//our custom flag to decide if proc dmg or shield
	PROC_ON_BLOCK_VICTIM				= 0x20000000,
	PROC_ON_SPELL_CRIT_HIT				= 0x40000000,
	PROC_TARGET_SELF					= 0x80000000,//our custom flag to decide if proc target is self or victim
};
#else
//REMEMBER: Wands r not ranged based weapons. So it shouldn't be any ranged proc when u hit with wands!
enum procFlags
{
	PROC_NULL                          = 0x0,
	PROC_ON_NPC_ACTION                 = 0x1, //on GO action too btw. related to quests in general.
	PROC_ON_XP_GAIN                    = 0x2, //on honor gain too btw.
	PROC_ON_MELEE_HIT                  = 0x4, //on successful white melee attack
	PROC_ON_MELEE_HIT_VICTIM           = 0x8, //on successful white melee attack victim
	PROC_ON_MELEE_ABILITY_LAND         = 0x10, //on successful melee ability attack. Abilities that was resisted/dodged etc doesn't proc with this flag
	PROC_ON_MELEE_ABILITY_LAND_VICTIM  = 0x20, //on successful melee ability victim but not white damage. Abilities that was resisted/dodged etc doesn't proc with this flag
	PROC_ON_RANGED_HIT                 = 0x40,  //on successful ranged white attack
	PROC_ON_RANGED_HIT_VICTIM          = 0x80,  //on successful ranged white attack victim
	PROC_ON_RANGED_ABILITY_LAND        = 0x100, //on successful ranged ability attack. Abilities that was resisted/dodged etc doesn't proc with this flag
	PROC_ON_RANGED_ABILITY_LAND_VICTIM = 0x200,  //on successful ranged ability victim but not white damage. Abilities that was resisted/dodged etc doesn't proc with this flag
	PROC_ON_CAST_SPELL                 = 0x400, //on nonability (spell) cast. Spells that was resisted don't proc with this flag
	PROC_ON_CAST_SPELL_VICTIM          = 0x800,  //on nonability (spell) cast victim. Spells that was resisted don't proc with this flag.
	PROC_ON_ANY_DAMAGE                 = 0x1000, // mb wrong
	PROC_ON_ANY_DAMAGE_VICTIM          = 0x2000, // mb wrong
	PROC_ON_HEALSPELL_LAND             = 0x4000, //on heal (direct or HoT) spell land.
	PROC_ON_HEALSPELL_LAND_VICTIM      = 0x8000,  //on heal (direct or HoT) spell land victim.
	PROC_ON_HARMFULSPELL_LAND          = 0x10000, //on harmfull spell land (DoT damage not included in this flag!)
	PROC_ON_HARMFULSPELL_LAND_VICTIM   = 0x20000, //on harmfull spell land victim (DoT damage not included in this flag!)
	PROC_ON_DOT_DAMAGE                 = 0x40000, //on harmfull non direct damage (DoTs)
	PROC_ON_DOT_DAMAGE_VICTIM          = 0x80000,  //on harmfull non direct damage (DoTs) victim
	PROC_REMOVEONUSE                   = 0x100000, //something supercustom. 99% wrong :P used by bombs and grenades in general.
	PROC_ON_TRAP_TRIGGER               = 0x200000,
	PROC_UNUSED1                       = 0x400000,
	PROC_ON_OFFHAND_HIT                = 0x800000, //only 1 spellname "Combat Potency"
	PROC_ON_UNK1                       = 0x1000000,//only 1 spellname "Captured Totem"
};
enum customProcFlags
{
	CUSTOMPROC_NULL                       = 0x0;
	CUSTOMPROC_ON_CRIT                    = 0x1; //doesn't matter victim or not. 
	CUSTOMPROC_ON_MISS_VICTIM             = 0x2;
	CUSTOMPROC_ON_DODGE_VICTIM            = 0x4;
	CUSTOMPROC_ON_BLOCK_VICTIM            = 0x8;
	CUSTOMPROC_ON_PARRY_VICTIM            = 0x10;
	CUSTOMPROC_ON_RESIST_VICTIM           = 0x20;
	CUSTOMPROC_ON_DIE                     = 0x40;//proc on our death
	CUSTOMPROC_ON_FINISHMOVE              = 0x80; //procs when we use finish move ability
	CUSTOMPROC_ON_ADDCOMBO                = 0x100; //procs when we use ability with +combo point
	CUSTOMPROC_PROC_ON_SELF               = 0x200; //proc on self
};
#endif

enum CastInterruptFlags
{
    CAST_INTERRUPT_NULL            = 0x0,
    CAST_INTERRUPT_ON_SILENCE      = 0x1,
    CAST_INTERRUPT_PUSHBACK        = 0x2, // seems to be whether or not the spell is pushed back on dmg
    CAST_INTERRUPT_ON_STUNNED      = 0x4, // could be wrong
    CAST_INTERRUPT_ON_MOVEMENT     = 0x8,
    CAST_INTERRUPT_ON_DAMAGE_TAKEN = 0x10
};

enum AuraInterruptFlags
{
    AURA_INTERRUPT_NULL                       = 0x0,
    AURA_INTERRUPT_ON_HOSTILE_SPELL_INFLICTED = 0x1,
    AURA_INTERRUPT_ON_ANY_DAMAGE_TAKEN        = 0x2,
    AURA_INTERRUPT_ON_UNK1                    = 0x4,
    AURA_INTERRUPT_ON_MOVEMENT                = 0x8, // could be AURA_INTERRUPT_ON_MOVEMENT
    AURA_INTERRUPT_ON_UNK2                    = 0x10,
    AURA_INTERRUPT_ON_UNK3                    = 0x20,
    AURA_INTERRUPT_ON_UNUSED1                 = 0x40,
    AURA_INTERRUPT_ON_SLOWED                  = 0x80,
    AURA_INTERRUPT_ON_LEAVE_WATER             = 0x100, // could be AURA_INTERRUPT_ON_LEAVE_CURRENT_SURFACE
    AURA_INTERRUPT_ON_UNUSED2                 = 0x200,
    AURA_INTERRUPT_ON_UNK4                    = 0x400,
    AURA_INTERRUPT_ON_UNK5                    = 0x800,
    AURA_INTERRUPT_ON_START_ATTACK            = 0x1000,
    AURA_INTERRUPT_ON_UNK6                    = 0x2000,
    AURA_INTERRUPT_ON_UNUSED3                 = 0x4000,
    AURA_INTERRUPT_ON_CAST_SPELL              = 0x8000,
    AURA_INTERRUPT_ON_UNK7                    = 0x10000,
    AURA_INTERRUPT_ON_MOUNT                   = 0x20000,
    AURA_INTERRUPT_ON_STAND_UP                = 0x40000,
    AURA_INTERRUPT_ON_LEAVE_AREA              = 0x80000,
    AURA_INTERRUPT_ON_INVINCIBLE              = 0x100000,
    AURA_INTERRUPT_ON_STEALTH                 = 0x200000,
    AURA_INTERRUPT_ON_UNK8                    = 0x400000,

    AURA_INTERRUPT_ON_AFTER_CAST_SPELL        = 0x80000000,
};

enum ChannelInterruptFlags
{
    CHANNEL_INTERRUPT_NULL  = 0x0,
    CHANNEL_INTERRUPT_ON_1  = 0x1,
    CHANNEL_INTERRUPT_ON_2  = 0x2,
    CHANNEL_INTERRUPT_ON_3  = 0x4,
    CHANNEL_INTERRUPT_ON_4  = 0x8,
    CHANNEL_INTERRUPT_ON_5  = 0x10,
    CHANNEL_INTERRUPT_ON_6  = 0x20,
    CHANNEL_INTERRUPT_ON_7  = 0x40,
    CHANNEL_INTERRUPT_ON_8  = 0x80,
    CHANNEL_INTERRUPT_ON_9  = 0x100,
    CHANNEL_INTERRUPT_ON_10 = 0x200,
    CHANNEL_INTERRUPT_ON_11 = 0x400,
    CHANNEL_INTERRUPT_ON_12 = 0x800,
    CHANNEL_INTERRUPT_ON_13 = 0x1000,
    CHANNEL_INTERRUPT_ON_14 = 0x2000,
    CHANNEL_INTERRUPT_ON_15 = 0x4000,
    CHANNEL_INTERRUPT_ON_16 = 0x8000,
    CHANNEL_INTERRUPT_ON_17 = 0x10000,
    CHANNEL_INTERRUPT_ON_18 = 0x20000
};

enum Attributes
{
	ATTRIBUTES_NULL								= 0x0,
	ATTRIBUTES_UNK2								= 0x1,
	ATTRIBUTES_UNK3								= 0x2, // related to ranged??
	ATTRIBUTE_ON_NEXT_ATTACK					= 0x4,
	ATTRIBUTES_UNUSED0							= 0x8,
	ATTRIBUTES_UNK6								= 0x10,
	ATTRIBUTES_UNK7								= 0x20, // Tradeskill recipies
	ATTRIBUTES_PASSIVE							= 0x40,
	ATTRIBUTES_NO_VISUAL_AURA					= 0x80,
	ATTRIBUTES_NO_CAST							= 0x100,	//seems to be afflicts pet
	ATTRIBUTES_UNK11							= 0x200, // looks like temp enchants.
	ATTRIBUTES_UNK12							= 0x400, //completely the same as ATTRIBUTE_ON_NEXT_ATTACK for class spells. So difference somewhere in mob abilities.
	ATTRIBUTES_UNK13							= 0x800,
	ATTRIBUTES_UNUSED1							= 0x1000,
	ATTRIBUTES_UNUSED2							= 0x2000,
	ATTRIBUTES_UNUSED3							= 0x4000,
	ATTRIBUTES_ONLY_OUTDOORS					= 0x8000,
	ATTRIBUTES_UNK								= 0x10000,
	ATTRIBUTES_REQ_STEALTH						= 0x20000,
	ATTRIBUTES_UNK20							= 0x40000,//it's not : must be behind
	ATTRIBUTES_UNK21							= 0x80000,
	ATTRIBUTES_STOP_ATTACK						= 0x100000,//switch off auto attack on use. Maim,Gouge,Disengage,Polymorph etc
	ATTRIBUTES_CANT_BE_DPB				    	= 0x200000,//can't be dodged, blocked, parried
	ATTRIBUTES_UNK24							= 0x400000, // related to ranged
	ATTRIBUTES_UNK25							= 0x800000,
	ATTRIBUTES_MOUNT_CASTABLE					= 0x1000000, //castable on mounts
	ATTRIBUTES_TRIGGER_COOLDOWN			        = 0x2000000, //also requires atributes ex = 32 ?
	ATTRIBUTES_UNK28							= 0x4000000,
	ATTRIBUTES_UNK29							= 0x8000000,
	ATTRIBUTES_REQ_OOC							= 0x10000000, //     ATTRIBUTES_REQ_OUT_OF_COMBAT
    ATTRIBUTES_IGNORE_INVULNERABILITY           = 0x20000000, //debuffs that can't be removed by any spell and spells that can't be resisted in any case
	ATTRIBUTES_UNK32							= 0x40000000, // seems like IS_DIMINISHING but some spells not there (f.e. Gouge)
	ATTRIBUTES_UNK33							= 0x80000000, // seems like aura is not removeable by CMSG_CANCEL_AURA
};

enum AttributesEx
{
	ATTRIBUTESEX_NULL                         = 0x0, // 0
	ATTRIBUTESEX_UNK2                         = 0x1, // 1, pet summonings
	ATTRIBUTESEX_DRAIN_WHOLE_MANA             = 0x2, // 2
	ATTRIBUTESEX_UNK4                         = 0x4, // 3
	ATTRIBUTESEX_UNK5                         = 0x8, // 4
	ATTRIBUTESEX_UNK6                         = 0x10, // 5, stealth effects but Rockbiter wtf 0_0
	ATTRIBUTESEX_NOT_BREAK_STEALTH            = 0x20, // 6
	ATTRIBUTESEX_UNK8						  = 0x40, // 7 [POSSIBLY: dynamite, grenades from engineering etc..]
	ATTRIBUTESEX_UNK9						  = 0x80,
	ATTRIBUTESEX_UNK10                        = 0x100,
	ATTRIBUTESEX_UNK11                        = 0x200,
	ATTRIBUTESEX_UNK12                        = 0x400,
	ATTRIBUTESEX_UNK13                        = 0x800,
	ATTRIBUTESEX_UNK14                        = 0x1000, // related to pickpocket
	ATTRIBUTESEX_UNK15                        = 0x2000, // related to remote control
	ATTRIBUTESEX_UNK16                        = 0x4000,
	ATTRIBUTESEX_UNK17                        = 0x8000, // something like "grant immunity"
	ATTRIBUTESEX_UNK18                        = 0x10000, // something like "grant immunity" too
	ATTRIBUTESEX_REMAIN_OOC                   = 0x20000,
	ATTRIBUTESEX_UNK20                        = 0x40000,
	ATTRIBUTESEX_UNK21                        = 0x80000,
	ATTRIBUTESEX_UNK22                        = 0x100000, // related to "Finishing move" and "Instantly overpowers"
	ATTRIBUTESEX_UNK23                        = 0x200000,
	ATTRIBUTESEX_UNK24                        = 0x400000, // only related to "Finishing move"
	ATTRIBUTESEX_UNK25                        = 0x800000, // related to spells like "ClearAllBuffs"
	ATTRIBUTESEX_UNK26                        = 0x1000000, // FISHING SPELLS
	ATTRIBUTESEX_UNK27                        = 0x2000000, // related to "Detect" spell
	ATTRIBUTESEX_UNK28                        = 0x4000000,
	ATTRIBUTESEX_UNK29                        = 0x8000000,
	ATTRIBUTESEX_UNK30                        = 0x10000000,
	ATTRIBUTESEX_UNK31                        = 0x20000000,
	ATTRIBUTESEX_UNK32                        = 0x40000000, // Overpower
	ATTRIBUTESEX_UNK33                        = 0x80000000,
};

enum Flags3
{
	FLAGS3_NULL               = 0x0,
	FLAGS3_UNK2               = 0x1,
	FLAGS3_UNK3               = 0x2,    // Can be used while stealthed
	FLAGS3_UNK4               = 0x4,    // request pet maybe
	FLAGS3_UNK5               = 0x8,    // something todo with temp enchanted items
	FLAGS3_PARTY_EFFECTING_AURA = 0x10, // Party affecting aura's
	FLAGS3_ACTIVATE_AUTO_SHOT = 0x20,   // spell that enable's auto shoot
	FLAGS3_UNK8               = 0x40,   //Polymorph spells
	FLAGS3_UNK9               = 0x80,
	FLAGS3_UNUSED1            = 0x100,
	FLAGS3_UNK11              = 0x200,  // used by 2 spells, 30421 | Nether Portal - Perseverence and  30466 | Nether Portal - Perseverence
	FLAGS3_TAME_X             = 0x400,  // tame [creature]
	FLAGS3_FUNNEL             = 0x800,  // only funnel spells
	FLAGS3_UNK14              = 0x1000, // swipe / Cleave spells
	FLAGS3_ENCHANT_OWN_ONLY   = 0x2000, // no trade window targets, BoE items get soulbound to you
	FLAGS3_SPELL_PLAYER_EVENT = 0x4000, // Player event's like logging in, finishing quests, triggering cinematic, being adored, Heartbroken etc
	FLAGS3_UNUSED3            = 0x8000,
	FLAGS3_CONTROL_UNIT       = 0x10000, // PvP Controller, RC, Creature taming, Taming Lesson
	FLAGS3_REQ_RANGED_WEAPON  = 0x20000, // this is shit and has nothing to do with auto shot
	FLAGS3_REVIVE_PET         = 0x40000, // actually 1 spell, revive pet
	FLAGS3_UNK21              = 0x80000, // this is a group of spells that are triggered by something. (I have no clue on how to name this one)
	FLAGS3_REQ_BEHIND_TARGET  = 0x100000, //wrong
	FLAGS3_UNK23              = 0x200000,
	FLAGS3_UNK24              = 0x400000,
	FLAGS3_UNK25              = 0x800000,
	FLAGS3_UNK26              = 0x1000000,
	FLAGS3_UNK27              = 0x2000000,
	FLAGS3_UNK28              = 0x4000000,
	FLAGS3_UNK29              = 0x8000000, // fishing spells and enchanting weapons
	FLAGS3_UNK30              = 0x10000000, // some secondairy spell triggers, especialy for lightning shield alike spells
	FLAGS3_UNK31              = 0x20000000,
	FLAGS3_UNK32              = 0x40000000,
	FLAGS3_UNK33              = 0x80000000,
};

enum Flags4
{
	FLAGS4_NULL							= 0x0,
	FLAGS4_UNK2							= 0x1,
	FLAGS4_UNK3							= 0x2,
	FLAGS4_UNK4							= 0x4,
	FLAGS4_UNK5							= 0x8,
	FLAGS4_UNK6							= 0x10,
	FLAGS4_UNK7							= 0x20,
	FLAGS4_UNK8							= 0x40,
	FLAGS4_UNK9							= 0x80,
	FLAGS4_UNK10						= 0x100,
	FLAGS4_UNK11						= 0x200,
	FLAGS4_UNK12						= 0x400,
	FLAGS4_BG_ONLY                      = 0x800,
	FLAGS4_UNK14						= 0x1000,
	FLAGS4_UNK15						= 0x2000,
	FLAGS4_UNK16						= 0x4000,
	FLAGS4_PLAYER_RANGED_SPELLS         = 0x8000,
	FLAGS4_UNK18						= 0x10000,
	FLAGS4_UNK19						= 0x20000,
	FLAGS4_UNK20						= 0x40000,
	FLAGS4_UNK21						= 0x80000,
	CAN_PERSIST_AND_CASTED_WHILE_DEAD   = 0x100000,
	FLAGS4_UNK23						= 0x200000,
	FLAGS4_PLAYER_RANGED_WAND           = 0x400000,
	FLAGS4_UNK25						= 0x800000,
	FLAGS4_UNK26						= 0x1000000,
	FLAGS4_UNK27						= 0x2000000,
	FLAGS4_UNK28						= 0x4000000,
	FLAGS4_UNK29						= 0x8000000,
	FLAGS4_UNK30						= 0x10000000,
	FLAGS4_UNK31						= 0x20000000,
	FLAGS4_UNK32						= 0x40000000,
	FLAGS4_UNK33						= 0x80000000,
};

enum Flags5
{
	FLAGS5_NULL							= 0x0,
	FLAGS5_UNK2							= 0x1,
	FLAGS5_PROCCHANCE_COMBOBASED        = 0x2,
	FLAGS5_UNK4							= 0x4,
	FLAGS5_UNK5							= 0x8,
	FLAGS5_UNK6							= 0x10,
	FLAGS5_UNK7							= 0x20,
	FLAGS5_UNK8							= 0x40,
	FLAGS5_UNK9							= 0x80,
	FLAGS5_UNK10						= 0x100,
	FLAGS5_UNK11						= 0x200,
	FLAGS5_UNK12						= 0x400,
	FLAGS5_UNK13						= 0x800,
	FLAGS5_UNK14						= 0x1000,
	FLAGS5_UNK15						= 0x2000,
	FLAGS5_UNK16						= 0x4000,
	FLAGS5_UNK17						= 0x8000,
	FLAGS5_UNK18						= 0x10000,
	FLAGS5_UNK19						= 0x20000,
	FLAGS5_UNK20						= 0x40000,
	FLAGS5_UNK21						= 0x80000,
	FLAGS5_UNK22						= 0x100000,
	FLAGS5_UNK23						= 0x200000,
	FLAGS5_UNK24						= 0x400000,
	FLAGS5_UNK25						= 0x800000,
	FLAGS5_UNK26						= 0x1000000,
	FLAGS5_UNK27						= 0x2000000,
	FLAGS5_ONLY_IN_OUTLANDS             = 0x4000000,
	FLAGS5_UNK29						= 0x8000000,
	FLAGS5_UNK30						= 0x10000000,
	FLAGS5_UNK31						= 0x20000000,
	FLAGS5_UNK32						= 0x40000000,
	FLAGS5_UNK33						= 0x80000000,
};

enum Flags6 
{
	FLAGS6_NULL							= 0x0,
	FLAGS6_UNK2							= 0x1,
	FLAGS6_UNK3							= 0x2,
	FLAGS6_UNK4							= 0x4,
	FLAGS6_UNK5							= 0x8,
	FLAGS6_UNK6							= 0x10,
	FLAGS6_UNK7							= 0x20,
	FLAGS6_UNK8							= 0x40,
	FLAGS6_UNK9							= 0x80,
	FLAGS6_UNK10						= 0x100,
	FLAGS6_UNK11						= 0x200,
	FLAGS6_UNK12						= 0x400,
	FLAGS6_UNK13						= 0x800,
	FLAGS6_UNK14						= 0x1000,
	FLAGS6_UNK15						= 0x2000,
	FLAGS6_UNK16						= 0x4000,
	FLAGS6_UNK17						= 0x8000,
	FLAGS6_UNK18						= 0x10000,
	FLAGS6_UNK19						= 0x20000,
	FLAGS6_UNK20						= 0x40000,
	FLAGS6_UNK21						= 0x80000,
	FLAGS6_UNK22						= 0x100000,
	FLAGS6_UNK23						= 0x200000,
	FLAGS6_UNK24						= 0x400000,
	FLAGS6_UNK25						= 0x800000,
	FLAGS6_UNK26						= 0x1000000,
	FLAGS6_UNK27						= 0x2000000,
	FLAGS6_UNK28						= 0x4000000,
	FLAGS6_UNK29						= 0x8000000,
	FLAGS6_UNK30						= 0x10000000,
	FLAGS6_UNK31						= 0x20000000,
	FLAGS6_UNK32						= 0x40000000,
	FLAGS6_UNK33						= 0x80000000,
};

enum Flags7
{
	FLAGS7_NULL							= 0x0,
	FLAGS7_UNK2							= 0x1,
	FLAGS7_UNUSED1						= 0x2, // unused 2.4.3
	FLAGS7_UNK4							= 0x4,
	FLAGS7_UNK5							= 0x8,
	FLAGS7_UNUSED2						= 0x10, // unused 2.4.3
	FLAGS7_UNK7							= 0x20,
	FLAGS7_UNK8							= 0x40,
	FLAGS7_UNK9							= 0x80,
	FLAGS7_UNK10						= 0x100,
	FLAGS7_UNUSED3						= 0x200, // unused 2.4.3
	FLAGS7_UNK12						= 0x400,
	FLAGS7_UNK13						= 0x800,
	FLAGS7_UNUSED4						= 0x1000, // unused 2.4.3
	FLAGS7_UNK15						= 0x2000,
	FLAGS7_UNUSED5						= 0x4000, // unused 2.4.3
	FLAGS7_UNUSED6						= 0x8000, // unused 2.4.3
	FLAGS7_UNUSED7						= 0x10000, // unused 2.4.3 - 20-33 also unused 2.4.3
	FLAGS7_UNK19						= 0x20000,
};

enum SpellCastFlags
{
    CAST_FLAG_UNKNOWN1           = 0x2,
    CAST_FLAG_UNKNOWN2           = 0x10, // no idea yet, i saw it in blizzard spell
    CAST_FLAG_AMMO               = 0x20 // load ammo display id (uint32) and ammo inventory type (uint32)
};

enum School
{
    SCHOOL_NORMAL = 0,
    SCHOOL_HOLY   = 1,
    SCHOOL_FIRE   = 2,
    SCHOOL_NATURE = 3,
    SCHOOL_FROST  = 4,
    SCHOOL_SHADOW = 5,
    SCHOOL_ARCANE = 6,
	SCHOOL_COUNT   
};

// converting schools for 2.4.0 client
static const uint32 g_spellSchoolConversionTable[SCHOOL_ARCANE+1] = {
	1,				// SCHOOL_NORMAL
	2,				// SCHOOL_HOLY
	4,				// SCHOOL_FIRE
	8,				// SCHOOL_NATURE
	16,				// SCHOOL_FROST
	32,				// SCHOOL_SHADOW
	64,				// SCHOOL_ARCANE
};

enum ReplenishType
{
    REPLENISH_UNDEFINED = 0,
    REPLENISH_HEALTH    = 20,
    REPLENISH_MANA      = 21,
    REPLENISH_RAGE      = 22 //don't know if rage is 22 or what, but will do for now
};

enum SpellTargetType
{
    TARGET_TYPE_NULL       = 0x0,
    TARGET_TYPE_BEAST      = 0x1,
    TARGET_TYPE_DRAGONKIN  = 0x2,
    TARGET_TYPE_DEMON      = 0x4,
    TARGET_TYPE_ELEMENTAL  = 0x8,
    TARGET_TYPE_GIANT      = 0x10,
    TARGET_TYPE_UNDEAD     = 0x20,
    TARGET_TYPE_HUMANOID   = 0x40,
    TARGET_TYPE_CRITTER    = 0x80,
    TARGET_TYPE_MECHANICAL = 0x100,
};

/****************SpellExtraFlags*****************/
/* SpellExtraFlags defines                      */
/*                                              */
/* Used for infront check and other checks      */
/* when they are not in spell.dbc               */
/*                                              */
/************************************************/
#define SPELL_EXTRA_INFRONT 1
#define SPELL_EXTRA_BEHIND  2
#define SPELL_EXTRA_UNDEF0  4 // not used yet
#define SPELL_EXTRA_UNDEF1  8 // not used yet


/***************Ranged spellid*******************/
/* Note: These spell id's are checked for 2.0.x */
/************************************************/
#define SPELL_RANGED_GENERAL    3018
#define SPELL_RANGED_THROW      2764
#define SPELL_RANGED_WAND       5019

#pragma pack(push,1)
struct TeleportCoords
{
    uint32 id;
    uint32 mapId;
    float x;
    float y;
    float z;
};
#pragma pack(pop)

struct TotemSpells
{
    uint32 spellId;
    uint32 spellToCast[3];
};

enum LOCKTYPES{
    LOCKTYPE_PICKLOCK               =1,
    LOCKTYPE_HERBALISM              =2,
    LOCKTYPE_MINING                 =3,
    LOCKTYPE_DISARM_TRAP            =4,
    LOCKTYPE_OPEN                   =5,
    LOCKTYPE_TREASURE               =6,
    LOCKTYPE_CALCIFIED_ELVEN_GEMS   =7,
    LOCKTYPE_CLOSE                  =8,
    LOCKTYPE_ARM_TRAP               =9,
    LOCKTYPE_QUICK_OPEN             =10,
    LOCKTYPE_QUICK_CLOSE            =11,
    LOCKTYPE_OPEN_TINKERING         =12,
    LOCKTYPE_OPEN_KNEELING          =13,
    LOCKTYPE_OPEN_ATTACKING         =14,
    LOCKTYPE_GAHZRIDIAN             =15,
    LOCKTYPE_BLASTING               =16,
    LOCKTYPE_SLOW_OPEN              =17,
    LOCKTYPE_SLOW_CLOSE             =18
};

enum SpellEffects
{
	SPELL_EFFECT_NULL = 0,
	SPELL_EFFECT_INSTANT_KILL,              //    1
	SPELL_EFFECT_SCHOOL_DAMAGE,             //    2
	SPELL_EFFECT_DUMMY,                     //    3
	SPELL_EFFECT_PORTAL_TELEPORT,           //    4
	SPELL_EFFECT_TELEPORT_UNITS,            //    5
	SPELL_EFFECT_APPLY_AURA,                //    6
	SPELL_EFFECT_ENVIRONMENTAL_DAMAGE,      //    7
	SPELL_EFFECT_POWER_DRAIN,               //    8
	SPELL_EFFECT_HEALTH_LEECH,              //    9
	SPELL_EFFECT_HEAL,                      //    10
	SPELL_EFFECT_BIND,                      //    11
	SPELL_EFFECT_PORTAL,                    //    12
	SPELL_EFFECT_RITUAL_BASE,               //    13
	SPELL_EFFECT_RITUAL_SPECIALIZE,         //    14
	SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL,    //    15
	SPELL_EFFECT_QUEST_COMPLETE,            //    16
	SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL,    //    17
	SPELL_EFFECT_RESURRECT,                 //    18
	SPELL_EFFECT_ADD_EXTRA_ATTACKS,         //    19
	SPELL_EFFECT_DODGE,                     //    20
	SPELL_EFFECT_EVADE,                     //    21
	SPELL_EFFECT_PARRY,                     //    22
	SPELL_EFFECT_BLOCK,                     //    23
	SPELL_EFFECT_CREATE_ITEM,               //    24
	SPELL_EFFECT_WEAPON,                    //    25
	SPELL_EFFECT_DEFENSE,                   //    26
	SPELL_EFFECT_PERSISTENT_AREA_AURA,      //    27
	SPELL_EFFECT_SUMMON,                    //    28
	SPELL_EFFECT_LEAP,                      //    29
	SPELL_EFFECT_ENERGIZE,                  //    30
	SPELL_EFFECT_WEAPON_PERCENT_DAMAGE,     //    31
	SPELL_EFFECT_TRIGGER_MISSILE,           //    32
	SPELL_EFFECT_OPEN_LOCK,                 //    33
	SPELL_EFFECT_TRANSFORM_ITEM,            //    34
	SPELL_EFFECT_APPLY_AREA_AURA,           //    35
	SPELL_EFFECT_LEARN_SPELL,               //    36
	SPELL_EFFECT_SPELL_DEFENSE,             //    37
	SPELL_EFFECT_DISPEL,                    //    38
	SPELL_EFFECT_LANGUAGE,                  //    39
	SPELL_EFFECT_DUAL_WIELD,                //    40
	SPELL_EFFECT_SUMMON_WILD,               //    41
	SPELL_EFFECT_SUMMON_GUARDIAN,           //    42
	SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER,//    43
	SPELL_EFFECT_SKILL_STEP,                //    44
	SPELL_EFFECT_UNDEFINED_45,              //    45
	SPELL_EFFECT_SPAWN,                     //    46
	SPELL_EFFECT_TRADE_SKILL,               //    47
	SPELL_EFFECT_STEALTH,                   //    48
	SPELL_EFFECT_DETECT,                    //    49
	SPELL_EFFECT_SUMMON_OBJECT,             //    50
	//SPELL_EFFECT_TRANS_DOOR,              //    50
	SPELL_EFFECT_FORCE_CRITICAL_HIT,        //    51
	SPELL_EFFECT_GUARANTEE_HIT,             //    52
	SPELL_EFFECT_ENCHANT_ITEM,              //    53
	SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY,    //    54
	SPELL_EFFECT_TAMECREATURE,              //    55
	SPELL_EFFECT_SUMMON_PET,                //    56
	SPELL_EFFECT_LEARN_PET_SPELL,           //    57
	SPELL_EFFECT_WEAPON_DAMAGE,             //    58
	SPELL_EFFECT_OPEN_LOCK_ITEM,            //    59
	SPELL_EFFECT_PROFICIENCY,               //    60
	SPELL_EFFECT_SEND_EVENT,                //    61
	SPELL_EFFECT_POWER_BURN,                //    62
	SPELL_EFFECT_THREAT,                    //    63
	SPELL_EFFECT_TRIGGER_SPELL,             //    64
	SPELL_EFFECT_HEALTH_FUNNEL,             //    65
	SPELL_EFFECT_POWER_FUNNEL,              //    66
	SPELL_EFFECT_HEAL_MAX_HEALTH,           //    67
	SPELL_EFFECT_INTERRUPT_CAST,            //    68
	SPELL_EFFECT_DISTRACT,                  //    69
	SPELL_EFFECT_PULL,                      //    70
	SPELL_EFFECT_PICKPOCKET,                //    71
	SPELL_EFFECT_ADD_FARSIGHT,              //    72
	SPELL_EFFECT_SUMMON_POSSESSED,          //    73
    SPELL_EFFECT_USE_GLYPH,	                //    74
	SPELL_EFFECT_HEAL_MECHANICAL,           //    75
	SPELL_EFFECT_SUMMON_OBJECT_WILD,        //    76
	SPELL_EFFECT_SCRIPT_EFFECT,             //    77
	SPELL_EFFECT_ATTACK,                    //    78
	SPELL_EFFECT_SANCTUARY,                 //    79
	SPELL_EFFECT_ADD_COMBO_POINTS,          //    80
	SPELL_EFFECT_CREATE_HOUSE,              //    81
	SPELL_EFFECT_BIND_SIGHT,                //    82
	SPELL_EFFECT_DUEL,                      //    83
	SPELL_EFFECT_STUCK,                     //    84
	SPELL_EFFECT_SUMMON_PLAYER,             //    85
	SPELL_EFFECT_ACTIVATE_OBJECT,           //    86
	SPELL_EFFECT_SUMMON_TOTEM_SLOT1,        //    87
	SPELL_EFFECT_SUMMON_TOTEM_SLOT2,        //    88
	SPELL_EFFECT_SUMMON_TOTEM_SLOT3,        //    89
	SPELL_EFFECT_SUMMON_TOTEM_SLOT4,        //    90
	SPELL_EFFECT_THREAT_ALL,                //    91
	SPELL_EFFECT_ENCHANT_HELD_ITEM,         //    92
	SPELL_EFFECT_SUMMON_PHANTASM,           //    93
	SPELL_EFFECT_SELF_RESURRECT,            //    94
	SPELL_EFFECT_SKINNING,                  //    95
	SPELL_EFFECT_CHARGE,                    //    96
	SPELL_EFFECT_SUMMON_CRITTER,            //    97
	SPELL_EFFECT_KNOCK_BACK,                //    98
	SPELL_EFFECT_DISENCHANT,                //    99
	SPELL_EFFECT_INEBRIATE,                 //    100
	SPELL_EFFECT_FEED_PET,                  //    101
	SPELL_EFFECT_DISMISS_PET,               //    102
	SPELL_EFFECT_REPUTATION,                //    103
	SPELL_EFFECT_SUMMON_OBJECT_SLOT1,       //    104
	SPELL_EFFECT_SUMMON_OBJECT_SLOT2,       //    105
	SPELL_EFFECT_SUMMON_OBJECT_SLOT3,       //    106
	SPELL_EFFECT_SUMMON_OBJECT_SLOT4,       //    107
	SPELL_EFFECT_DISPEL_MECHANIC,           //    108
	SPELL_EFFECT_SUMMON_DEAD_PET,           //    109
	SPELL_EFFECT_DESTROY_ALL_TOTEMS,        //    110
	SPELL_EFFECT_DURABILITY_DAMAGE,         //    111
	SPELL_EFFECT_SUMMON_DEMON,              //    112
	SPELL_EFFECT_RESURRECT_FLAT,            //    113
	SPELL_EFFECT_ATTACK_ME,                 //    114
	SPELL_EFFECT_DURABILITY_DAMAGE_PCT,     //    115
	SPELL_EFFECT_SKIN_PLAYER_CORPSE,        //    116
	SPELL_EFFECT_SPIRIT_HEAL,               //    117
	SPELL_EFFECT_SKILL,                     //    118
	SPELL_EFFECT_APPLY_PET_AURA,            //    119
	SPELL_EFFECT_TELEPORT_GRAVEYARD,        //    120
	SPELL_EFFECT_DUMMYMELEE,                //    121
	SPELL_EFFECT_UNKNOWN1,                  //    122
	SPELL_EFFECT_FILMING,                   //    123
	SPELL_EFFECT_PLAYER_PULL,               //    124
	SPELL_EFFECT_UNKNOWN4,                  //    125
	SPELL_EFFECT_UNKNOWN5,                  //    126
	SPELL_EFFECT_PROSPECTING,               //    127
	SPELL_EFFECT_UNKNOWN7,                  //    128
	SPELL_EFFECT_UNKNOWN8,                  //    129
//	SPELL_EFFECT_UNKNOWN9,                  //    129
	SPELL_EFFECT_UNKNOWN10,                 //    130
	SPELL_EFFECT_UNKNOWN11,                 //    131
	SPELL_EFFECT_UNKNOWN12,                 //    132
	SPELL_EFFECT_FORGET_SPECIALIZATION,     //    133
	SPELL_EFFECT_UNKNOWN14,                 //    134
	SPELL_EFFECT_UNKNOWN15,                 //    135
	SPELL_EFFECT_UNKNOWN16,                 //    136
	SPELL_EFFECT_UNKNOWN17,                 //    137
	SPELL_EFFECT_UNKNOWN18,                 //    138
	SPELL_EFFECT_UNKNOWN19,                 //    139
	SPELL_EFFECT_UNKNOWN20,                 //    140
	SPELL_EFFECT_UNKNOWN21,                 //    141
	SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE,  //    142
	SPELL_EFFECT_UNKNOWN22,                 //    143
	SPELL_EFFECT_UNKNOWN23,                 //    144
	SPELL_EFFECT_UNKNOWN24,                 //    145
	SPELL_EFFECT_UNKNOWN25,                 //    146
	SPELL_EFFECT_UNKNOWN26,                 //    147
	SPELL_EFFECT_UNKNOWN27,                 //    148
	SPELL_EFFECT_QUEST_FAIL,                //    149
	SPELL_EFFECT_UNKNOWN28,                 //    150
	SPELL_EFFECT_UNKNOWN29,                 //    151
	SPELL_EFFECT_UNKNOWN30,                 //    152
	SPELL_EFFECT_SUMMON_TARGET,             //    153
	SPELL_EFFECT_SUMMON_REFER_A_FRIEND,     //    154
	SPELL_EFFECT_TAME_CREATURE,             //    155
	SPELL_EFFECT_UNKNOWN34,                 //    156
	SPELL_EFFECT_UNKNOWN35,                 //    157
	SPELL_EFFECT_UNKNOWN36,                 //    158
	SPELL_EFFECT_UNKNOWN37,                 //    159
	SPELL_EFFECT_UNKNOWN38,                 //    160
	SPELL_EFFECT_UNKNOWN39,                 //    161
    TOTAL_SPELL_EFFECTS,                    //    162
};

// target type flags
enum SpellTargetTypes
{
    SPELL_TARGET_TYPE_NONE              = 0x01,
    SPELL_TARGET_TYPE_PROFESSION        = 0x02,
    SPELL_TARGET_TYPE_NONE1             = 0x04,
    SPELL_TARGET_TYPE_NONE2             = 0x08,
    SPELL_TARGET_TYPE_ENCHANTABLE_ITEM  = 0x10,
    SPELL_TARGET_TYPE_UNK               = 0x20,     // seems to be scripted stuff
    SPELL_TARGET_TYPE_UNK0              = 0x40,     // lots of spells interesting to research this one further
    SPELL_TARGET_TYPE_UNK1              = 0x80,     // something todo with scripted and GM stuff
    SPELL_TARGET_TYPE_UNK2              = 0x100,    // lots of spells interesting to research this one further...
    SPELL_TARGET_TYPE_PLAYER_CORPSE     = 0x200,
    SPELL_TARGET_TYPE_DEATHx            = 0x400,
    SPELL_TARGET_TYPE_NONE3             = 0x800,
    SPELL_TARGET_TYPE_NONE4             = 0x1000,
    SPELL_TARGET_TYPE_NONE5             = 0x2000,
    SPELL_TARGET_TYPE_GAME_OBJECTS      = 0x4000, // like chests and mining
    SPELL_TARGET_TYPE_DEATH             = 0x8000,
};

enum SpellTypes // SPELL_ENTRY_buffType
{
    SPELL_TYPE_NONE                 = 0x00000000,
    SPELL_TYPE_SEAL                 = 0x00000001,
    SPELL_TYPE_ASPECT               = 0x00000002,
    SPELL_TYPE_BLESSING             = 0x00000004,
    SPELL_TYPE_CURSE                = 0x00000008,
    SPELL_TYPE_STING                = 0x00000010,
    SPELL_TYPE_ARMOR                = 0x00000020,
    SPELL_TYPE_AURA                 = 0x00000040,
    //hmm these could be named simply incompatible spells. One active at a time
    SPELL_TYPE_MARK_GIFT            = 0x00000080,
    SPELL_TYPE_TRACK                = 0x00000100,
    SPELL_TYPE_HUNTER_TRAP          = 0x00000200,
    SPELL_TYPE_MAGE_INTEL           = 0x00000400,
    SPELL_TYPE_MAGE_MAGI            = 0x00000800,
    SPELL_TYPE_MAGE_WARDS           = 0x00001000,
    SPELL_TYPE_PRIEST_SH_PPROT      = 0x00002000,
    SPELL_TYPE_SHIELD               = 0x00004000,
    SPELL_TYPE_FORTITUDE            = 0x00008000,
    SPELL_TYPE_SPIRIT               = 0x00010000,
    SPELL_TYPE_MAGE_AMPL_DUMP       = 0x00020000,
    SPELL_TYPE_WARLOCK_IMMOLATE     = 0x00040000, //maybe there is a better way to trigger the aura state for immolate spell
    SPELL_TYPE_ELIXIR_BATTLE		= 0x00080000, 
    SPELL_TYPE_ELIXIR_GUARDIAN      = 0x00100000, 
    SPELL_TYPE_ELIXIR_FLASK         = SPELL_TYPE_ELIXIR_BATTLE | SPELL_TYPE_ELIXIR_GUARDIAN, //weee, this contains both battle and guardian elixirs ;)
    SPELL_TYPE_HUNTER_MARK			= 0x00200000,
    SPELL_TYPE_WARRIOR_SHOUT        = 0x00400000,
	SPELL_TYPE_QUIVER_HASTE			= 0x00800000,
	SPELL_TYPE_CORRUPTION			= 0x01000000,
};

//custom stuff generated for spells that will not change in time
enum SpellIsFlags
{
    SPELL_FLAG_IS_DAMAGING				= 0x00000001,
    SPELL_FLAG_IS_HEALING				= 0x00000002,
    SPELL_FLAG_IS_TARGETINGSTEALTHED	= 0x00000004,
    SPELL_FLAG_IS_REQUIRECOOLDOWNUPDATE	= 0x00000008, //it started with rogue cold blood but i'm sure others will come
    SPELL_FLAG_IS_POISON				= 0x00000010, //rogue has a few spells that can stack so can't use the spell_type enum ;)
    SPELL_FLAG_IS_FINISHING_MOVE		= 0x00000020, //rogue has a few spells that can stack so can't use the spell_type enum ;)
    SPELL_FLAG_IS_NOT_USING_DMG_BONUS	= 0x00000040, 
    SPELL_FLAG_IS_CHILD_SPELL			= 0x00000080, //auras proc auras that have same name, these should not remove mother aura when adding to target
    SPELL_FLAG_IS_CASTED_ON_PET_SUMMON_ON_PET		= 0x00000100, //we should cast these on pet too
    SPELL_FLAG_IS_CASTED_ON_PET_SUMMON_PET_OWNER	= 0x00000200, //we should cast these on owner too
    SPELL_FLAG_IS_EXPIREING_WITH_PET	= 0x00000400, //when pet dies, we remove this too
    SPELL_FLAG_IS_EXPIREING_ON_PET		= 0x00000800, //when pet is summoned
	SPELL_FLAG_IS_FORCEDDEBUFF			= 0x00001000, // forced to be a debuff
	SPELL_FLAG_IS_FORCEDBUFF			= 0x00002000, // forced to be a buff
	SPELL_FLAG_IS_INHERITING_LEVEL		= 0x00004000, // summons to inherit caster level or not
	SPELL_FLAG_IS_MAXSTACK_FOR_DEBUFF	= 0x00008000, // summons to inherit caster level or not
};

enum SpellCoefficientsFlags
{
	SPELL_FLAG_IS_DOT_OR_HOT_SPELL		= 0x00000001, //Damage over Time or Healing over Time Spells
	SPELL_FLAG_IS_DD_OR_DH_SPELL		= 0x00000002, //Direct Damage or Direct Healing Spells
	SPELL_FLAG_IS_DD_DH_DOT_SPELL		= SPELL_FLAG_IS_DOT_OR_HOT_SPELL | SPELL_FLAG_IS_DD_OR_DH_SPELL, //DoT+(DD|DH) Spells
	SPELL_FLAG_AOE_SPELL				= 0x00000004, //AoE Spells
	SPELL_FLAG_ADITIONAL_EFFECT			= 0x00000008, //Spells with aditional effect not DD or DoT or HoT
};

enum DiminishingGroup
{
	DIMINISHING_GROUP_STUN				= 0,
	DIMINISHING_GROUP_STUN_PROC			= 1,
	DIMINISHING_GROUP_ROOT				= 2,
	DIMINISHING_GROUP_ROOT_PROC			= 3,
	DIMINISHING_GROUP_SLEEP				= 4,
	DIMINISHING_GROUP_BLIND_CYCLONE		= 5,
	DIMINISHING_GROUP_GOUGE_POLY_SAP	= 6,
	DIMINISHING_GROUP_FEAR				= 7,
	DIMINISHING_GROUP_CHARM				= 8,
	DIMINISHING_GROUP_KIDNEY_SHOT		= 9,
	DIMINISHING_GROUP_HORROR			= 10,
	DIMINISHING_GROUP_BANISH			= 11,
	DIMINISHING_GROUP_NOT_DIMINISHED			= 12,
	DIMINISHING_GROUP_DISARM			= 13,
};

ARCEMU_INLINE bool CanAgroHash(uint32 spellhashname)
{
    if (spellhashname == 4287212498UL) //hunter's mark
        return false;
    else
        return true;
}

/************************************************************************/
/* IsDamagingSpell, this function seems slow, its only used rarely      */
/************************************************************************/
ARCEMU_INLINE bool IsDamagingSpell(SpellEntry *sp)
{
    switch (sp->Effect[0])
    {
        case SPELL_EFFECT_SCHOOL_DAMAGE:
        case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE:
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
        case SPELL_EFFECT_ADD_EXTRA_ATTACKS:
        case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
        case SPELL_EFFECT_POWER_BURN:
        case SPELL_EFFECT_ATTACK:
            return true;
    }
    switch (sp->Effect[1])
    {
        case SPELL_EFFECT_SCHOOL_DAMAGE:
        case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE:
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
        case SPELL_EFFECT_ADD_EXTRA_ATTACKS:
        case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
        case SPELL_EFFECT_POWER_BURN:
        case SPELL_EFFECT_ATTACK:
            return true;
    }
    switch (sp->Effect[2])
    {
        case SPELL_EFFECT_SCHOOL_DAMAGE:
        case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE:
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
        case SPELL_EFFECT_ADD_EXTRA_ATTACKS:
        case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
        case SPELL_EFFECT_POWER_BURN:
        case SPELL_EFFECT_ATTACK:
            return true;
    }
    if( sp->Effect[0]==SPELL_EFFECT_APPLY_AURA ||
       sp->Effect[0]==SPELL_EFFECT_APPLY_AREA_AURA)
    {
        switch (sp->EffectApplyAuraName[0])
        {
            case 3://SPELL_AURA_PERIODIC_DAMAGE:
            case 43://SPELL_AURA_PROC_TRIGGER_DAMAGE:
            case 89://SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
            case 162://SPELL_AURA_POWER_BURN:
                return true;
        }
    }
    if( sp->Effect[1]==SPELL_EFFECT_APPLY_AURA ||
        sp->Effect[1]==SPELL_EFFECT_APPLY_AREA_AURA)
    {
        switch (sp->EffectApplyAuraName[1])
        {
            case 3://SPELL_AURA_PERIODIC_DAMAGE:
            case 43://SPELL_AURA_PROC_TRIGGER_DAMAGE:
            case 89://SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
            case 162://SPELL_AURA_POWER_BURN:
                return true;
        }
    }
    if( sp->Effect[2]==SPELL_EFFECT_APPLY_AURA ||
        sp->Effect[2]==SPELL_EFFECT_APPLY_AREA_AURA)
    {
        switch (sp->EffectApplyAuraName[2])
        {
            case 3://SPELL_AURA_PERIODIC_DAMAGE:
            case 43://SPELL_AURA_PROC_TRIGGER_DAMAGE:
            case 89://SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
            case 162://SPELL_AURA_POWER_BURN:
                return true;
        }
    }
    return false;
}

ARCEMU_INLINE uint32 IsHealingSpell(SpellEntry *sp)
{
    switch( sp->Effect[0] )
    {
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_HEAL:
        case SPELL_EFFECT_HEALTH_FUNNEL:
        case SPELL_EFFECT_HEAL_MAX_HEALTH:
            return 1;
		default: break;
    }
    switch( sp->Effect[1] )
    {
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_HEAL:
        case SPELL_EFFECT_HEALTH_FUNNEL:
        case SPELL_EFFECT_HEAL_MAX_HEALTH:
            return 2;
		default: break;
    }
    switch( sp->Effect[2] )
    {
        case SPELL_EFFECT_HEALTH_LEECH:
        case SPELL_EFFECT_HEAL:
        case SPELL_EFFECT_HEALTH_FUNNEL:
        case SPELL_EFFECT_HEAL_MAX_HEALTH:
            return 3;
		default: break;
    }
    if( sp->Effect[0] == SPELL_EFFECT_APPLY_AURA ||
		sp->Effect[0] == SPELL_EFFECT_APPLY_AREA_AURA )
    {
        switch( sp->EffectApplyAuraName[0] )
        {
            case 8://SPELL_AURA_PERIODIC_HEAL:
            case 62://SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
                return 1;
			default: break;
        }
    }
    if( sp->Effect[1] == SPELL_EFFECT_APPLY_AURA ||
        sp->Effect[1] == SPELL_EFFECT_APPLY_AREA_AURA )
    {
        switch (sp->EffectApplyAuraName[1])
        {
            case 8://SPELL_AURA_PERIODIC_HEAL:
            case 62://SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
                return 2;
			default: break;
        }
    }
    if( sp->Effect[2] == SPELL_EFFECT_APPLY_AURA ||
        sp->Effect[2] == SPELL_EFFECT_APPLY_AREA_AURA )
    {
        switch( sp->EffectApplyAuraName[2] )
        {
            case 8://SPELL_AURA_PERIODIC_HEAL:
            case 62://SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
                return 3;
			default: break;
        }
    }
	//flash of light, holy light uses scripted effect which is not neceserally heal spell
	if( sp->NameHash == SPELL_HASH_HOLY_LIGHT || sp->NameHash == SPELL_HASH_FLASH_OF_LIGHT  )
		return true;
	
    return false;
}

ARCEMU_INLINE bool IsInrange(LocationVector & location, Object * o, float square_r)
{
    float r = o->GetDistanceSq(location);
    return ( r<=square_r);
}

ARCEMU_INLINE bool IsInrange(float x1,float y1, float z1, Object * o,float square_r)
{
    float r = o->GetDistanceSq(x1, y1, z1);
    return ( r<=square_r);
}

ARCEMU_INLINE bool IsInrange(float x1,float y1, float z1,float x2,float y2, float z2,float square_r)
{
    float t;
    float r;
    t=x1-x2;
    r=t*t;
    t=y1-y2;
    r+=t*t;
    t=z1-z2;
    r+=t*t;
    return ( r<=square_r);
}
   
ARCEMU_INLINE bool IsInrange(Object * o1,Object * o2,float square_r)
{
    return IsInrange(o1->GetPositionX(),o1->GetPositionY(),o1->GetPositionZ(),
        o2->GetPositionX(),o2->GetPositionY(),o2->GetPositionZ(),square_r);
}

ARCEMU_INLINE bool TargetTypeCheck(Object *obj,uint32 ReqCreatureTypeMask)
{
	if( !ReqCreatureTypeMask )
		return true;

	if( obj->GetTypeId() == TYPEID_UNIT )
	{
		CreatureInfo* inf = static_cast< Creature* >( obj )->GetCreatureInfo();
		if( inf == NULL || !( 1 << ( inf->Type - 1 ) & ReqCreatureTypeMask ) )
			return false;
	}
	else if(obj->GetTypeId() == TYPEID_PLAYER && !(UNIT_TYPE_HUMANOID_BIT & ReqCreatureTypeMask))
		return false;
	else return false;//omg, how in the hack did we cast it on a GO ? But who cares ?
	return true;
}

class SpellCastTargets
{
public:
    void read ( WorldPacket & data,uint64 caster );
    void write ( WorldPacket & data);

    SpellCastTargets() : m_targetMask(0), m_targetMaskExtended(0), m_unitTarget(0), m_itemTarget(0), m_srcX(0), m_srcY(0), m_srcZ(0),
        m_destX(0), m_destY(0), m_destZ(0), m_strTarget(NULL) {}

    SpellCastTargets(uint16 TargetMask, uint64 unitTarget, uint64 itemTarget, float srcX, float srcY,
        float srcZ, float destX, float destY, float destZ) : m_targetMask(TargetMask), m_targetMaskExtended(0), m_unitTarget(unitTarget),
        m_itemTarget(itemTarget), m_srcX(srcX), m_srcY(srcY), m_srcZ(srcZ), m_destX(destX), m_destY(destY), m_destZ(destZ), m_strTarget(NULL) {}

    SpellCastTargets(uint64 unitTarget) : m_targetMask(0x2), m_targetMaskExtended(0), m_unitTarget(unitTarget), m_itemTarget(0),
        m_srcX(0), m_srcY(0), m_srcZ(0), m_destX(0), m_destY(0), m_destZ(0), m_strTarget(NULL) {}

    SpellCastTargets(WorldPacket & data, uint64 caster) : m_targetMask(0), m_targetMaskExtended(0), m_unitTarget(0), m_itemTarget(0), m_srcX(0), m_srcY(0), m_srcZ(0),
        m_destX(0), m_destY(0), m_destZ(0), m_strTarget(NULL)
    {
        read(data, caster);
    }

    SpellCastTargets& operator=(const SpellCastTargets &target)
    {
        m_unitTarget = target.m_unitTarget;
        m_itemTarget = target.m_itemTarget;

        m_srcX = target.m_srcX;
        m_srcY = target.m_srcY;
        m_srcZ = target.m_srcZ;

        m_destX = target.m_destX;
        m_destY = target.m_destY;
        m_destZ = target.m_destZ;

		m_strTarget = target.m_strTarget ? strdup(target.m_strTarget) : NULL;

        m_targetMask = target.m_targetMask;
	m_targetMaskExtended = target.m_targetMaskExtended;

        return *this;
    }

    uint16 m_targetMask;
    uint16 m_targetMaskExtended;			// this could be a 32 also
    uint64 m_unitTarget;
    uint64 m_itemTarget;
    float m_srcX, m_srcY, m_srcZ;
    float m_destX, m_destY, m_destZ;
    char* m_strTarget;

};

enum SpellState
{
    SPELL_STATE_NULL      = 0,
    SPELL_STATE_PREPARING = 1,
    SPELL_STATE_CASTING   = 2,
    SPELL_STATE_FINISHED  = 3,
    SPELL_STATE_IDLE      = 4
};

enum DISPEL_TYPE
{
    DISPEL_ZGTRINKETS		= -1,
    DISPEL_NULL				= 0,
    DISPEL_MAGIC			= 1,
    DISPEL_CURSE			= 2,
    DISPEL_DISEASE			= 3,
    DISPEL_POISON			= 4,
    DISPEL_STEALTH			= 5,
    DISPEL_INVISIBILTY		= 6,
    DISPEL_ALL				= 7,
    DISPEL_SPECIAL_NPCONLY	= 8,
    DISPEL_FRENZY			= 9,
};

enum MECHANICS
{
    MECHANIC_CHARMED = 1,
    MECHANIC_DISORIENTED, // 2
    MECHANIC_DISARMED, // 3
    MECHANIC_DISTRACED, // 4
    MECHANIC_FLEEING, // 5
    MECHANIC_CLUMSY, // 6
    MECHANIC_ROOTED, // 7
    MECHANIC_PACIFIED, // 8
    MECHANIC_SILENCED, // 9
    MECHANIC_ASLEEP, // 10
    MECHANIC_ENSNARED, // 11
	MECHANIC_STUNNED, // 12
	MECHANIC_FROZEN, // 13
	MECHANIC_INCAPACIPATED, // 14
	MECHANIC_BLEEDING, // 15
	MECHANIC_HEALING, // 16
	MECHANIC_POLYMORPHED, // 17
	MECHANIC_BANISHED, // 18
	MECHANIC_SHIELDED, // 19
	MECHANIC_SHACKLED, // 20
	MECHANIC_MOUNTED, // 21
	MECHANIC_SEDUCED, // 22
	MECHANIC_TURNED, // 23
	MECHANIC_HORRIFIED, // 24
	MECHANIC_INVULNARABLE, // 25
	MECHANIC_INTERRUPTED, // 26
	MECHANIC_DAZED, // 27
	MECHANIC_DISCOVERY, // 28
	MECHANIC_INVULNERABLE, // 29
	MECHANIC_SAPPED // 30
};

typedef enum {
   EFF_TARGET_NONE										= 0,
   EFF_TARGET_SELF										= 1,
   EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS		= 3,
   EFF_TARGET_PET										= 5,
   EFF_TARGET_SINGLE_ENEMY								= 6,
   EFF_TARGET_SCRIPTED_TARGET							= 7,
   EFF_TARGET_ALL_TARGETABLE_AROUND_LOCATION_IN_RADIUS  = 8,
   EFF_TARGET_HEARTSTONE_LOCATION						= 9,
   EFF_TARGET_ALL_ENEMY_IN_AREA							= 15,
   EFF_TARGET_ALL_ENEMY_IN_AREA_INSTANT					= 16,
   EFF_TARGET_TELEPORT_LOCATION							= 17,
   EFF_TARGET_LOCATION_TO_SUMMON						= 18,
   EFF_TARGET_ALL_PARTY_AROUND_CASTER					= 20,
   EFF_TARGET_SINGLE_FRIEND								= 21,
   EFF_TARGET_ALL_ENEMIES_AROUND_CASTER					= 22,
   EFF_TARGET_GAMEOBJECT								= 23,
   EFF_TARGET_IN_FRONT_OF_CASTER						= 24,
   EFF_TARGET_DUEL										= 25,//Dont know the real name!!!
   EFF_TARGET_GAMEOBJECT_ITEM							= 26,
   EFF_TARGET_PET_MASTER								= 27,
   EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED				= 28,
   EFF_TARGET_ALL_PARTY_IN_AREA_CHANNELED				= 29,
   EFF_TARGET_ALL_FRIENDLY_IN_AREA						= 30,
   EFF_TARGET_ALL_TARGETABLE_AROUND_LOCATION_IN_RADIUS_OVER_TIME	= 31,
   EFF_TARGET_MINION									= 32,
   EFF_TARGET_ALL_PARTY_IN_AREA							= 33,
   EFF_TARGET_SINGLE_PARTY								= 35,
   EFF_TARGET_PET_SUMMON_LOCATION						= 36,
   EFF_TARGET_ALL_PARTY									= 37,
   EFF_TARGET_SCRIPTED_OR_SINGLE_TARGET					= 38,
   EFF_TARGET_SELF_FISHING								= 39,
   EFF_TARGET_SCRIPTED_GAMEOBJECT						= 40,
   EFF_TARGET_TOTEM_EARTH								= 41,
   EFF_TARGET_TOTEM_WATER								= 42,
   EFF_TARGET_TOTEM_AIR									= 43,
   EFF_TARGET_TOTEM_FIRE								= 44,
   EFF_TARGET_CHAIN										= 45,
   EFF_TARGET_SCIPTED_OBJECT_LOCATION					= 46,
   EFF_TARGET_DYNAMIC_OBJECT							= 47,//not sure exactly where is used
   EFF_TARGET_MULTIPLE_SUMMON_LOCATION					= 48,
   EFF_TARGET_MULTIPLE_SUMMON_PET_LOCATION				= 49,
   EFF_TARGET_SUMMON_LOCATION							= 50,
   EFF_TARGET_CALIRI_EGS								= 51,
   EFF_TARGET_LOCATION_NEAR_CASTER						= 52,
   EFF_TARGET_CURRENT_SELECTION							= 53,
   EFF_TARGET_TARGET_AT_ORIENTATION_TO_CASTER			= 54,
   EFF_TARGET_LOCATION_INFRONT_CASTER					= 55,
   EFF_TARGET_PARTY_MEMBER								= 57,
   EFF_TARGET_TARGET_FOR_VISUAL_EFFECT					= 59,
   EFF_TARGET_SCRIPTED_TARGET2							= 60,
   EFF_TARGET_AREAEFFECT_PARTY_AND_CLASS				= 61,
   EFF_TARGET_PRIEST_CHAMPION							= 62, //wtf ?
   EFF_TARGET_NATURE_SUMMON_LOCATION					= 63, 
   EFF_TARGET_BEHIND_TARGET_LOCATION					= 65, 
   EFF_TARGET_MULTIPLE_GUARDIAN_SUMMON_LOCATION			= 72,
   EFF_TARGET_NETHETDRAKE_SUMMON_LOCATION				= 73,
   EFF_TARGET_SCRIPTED_LOCATION							= 74,
   EFF_TARGET_LOCATION_INFRONT_CASTER_AT_RANGE			= 75,
   EFF_TARGET_ENEMYS_IN_ARE_CHANNELED_WITH_EXCEPTIONS	= 76,
   EFF_TARGET_SELECTED_ENEMY_CHANNELED					= 77,
   EFF_TARGET_SELECTED_ENEMY_DEADLY_POISON				= 86,
	//these are custom, feel free to move them further if tageting gets extended
   EFF_TARGET_CUSTOM_PARTY_INJURED_SINGLE				= 99,
   EFF_TARGET_CUSTOM_PARTY_INJURED_MULTI				= 100,
   EFF_TARGET_LIST_LENGTH_MARKER						= 101,
} SpellEffectTarget;


inline bool HasTargetType(SpellEntry *sp,uint32 ttype)
{
	if( 
		sp->EffectImplicitTargetA[0]==ttype ||
		sp->EffectImplicitTargetA[1]==ttype ||
		sp->EffectImplicitTargetA[2]==ttype ||
		sp->EffectImplicitTargetB[0]==ttype ||
		sp->EffectImplicitTargetB[1]==ttype ||
		sp->EffectImplicitTargetB[2]==ttype
		)
		return true;
	return false;
}

inline int GetAiTargetType(SpellEntry *sp)
{
	/*	this is not good as one spell effect can target self and other one an enemy,
		maybe we should make it for each spell effect or use as flags */	
	if( 
		HasTargetType(sp,EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS) ||
		HasTargetType(sp,EFF_TARGET_ALL_TARGETABLE_AROUND_LOCATION_IN_RADIUS) ||
		HasTargetType(sp,EFF_TARGET_ALL_ENEMY_IN_AREA) ||
		HasTargetType(sp,EFF_TARGET_ALL_ENEMY_IN_AREA_INSTANT) ||
		HasTargetType(sp,EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED) ||
		HasTargetType(sp,EFF_TARGET_ALL_TARGETABLE_AROUND_LOCATION_IN_RADIUS_OVER_TIME)
		)
		return TTYPE_DESTINATION;
	if( 
		HasTargetType(sp,EFF_TARGET_LOCATION_TO_SUMMON) ||
		HasTargetType(sp,EFF_TARGET_IN_FRONT_OF_CASTER) ||
		HasTargetType(sp,EFF_TARGET_ALL_FRIENDLY_IN_AREA) ||
		HasTargetType(sp,EFF_TARGET_PET_SUMMON_LOCATION) ||
		HasTargetType(sp,EFF_TARGET_LOCATION_INFRONT_CASTER)
		)
		return TTYPE_SOURCE;
	if( 
		HasTargetType(sp,EFF_TARGET_SINGLE_ENEMY) ||
		HasTargetType(sp,EFF_TARGET_ALL_ENEMIES_AROUND_CASTER) ||
		HasTargetType(sp,EFF_TARGET_DUEL) ||
		HasTargetType(sp,EFF_TARGET_SCRIPTED_OR_SINGLE_TARGET) ||
		HasTargetType(sp,EFF_TARGET_CHAIN) ||
		HasTargetType(sp,EFF_TARGET_CURRENT_SELECTION) ||
		HasTargetType(sp,EFF_TARGET_TARGET_AT_ORIENTATION_TO_CASTER) ||
		HasTargetType(sp,EFF_TARGET_MULTIPLE_GUARDIAN_SUMMON_LOCATION) ||
		HasTargetType(sp,EFF_TARGET_SELECTED_ENEMY_CHANNELED)
		)
		return TTYPE_SINGLETARGET;
	if( 
		HasTargetType(sp,EFF_TARGET_ALL_PARTY_AROUND_CASTER) ||
		HasTargetType(sp,EFF_TARGET_SINGLE_FRIEND) ||
		HasTargetType(sp,EFF_TARGET_PET_MASTER) ||
		HasTargetType(sp,EFF_TARGET_ALL_PARTY_IN_AREA_CHANNELED) ||
		HasTargetType(sp,EFF_TARGET_ALL_PARTY_IN_AREA) ||
		HasTargetType(sp,EFF_TARGET_SINGLE_PARTY) ||
		HasTargetType(sp,EFF_TARGET_ALL_PARTY) ||
		HasTargetType(sp,EFF_TARGET_PARTY_MEMBER) ||
		HasTargetType(sp,EFF_TARGET_AREAEFFECT_PARTY_AND_CLASS)
		)
		return TTYPE_OWNER;
	if( 
		HasTargetType(sp,EFF_TARGET_SELF) ||
		HasTargetType(sp,4) ||
		HasTargetType(sp,EFF_TARGET_PET) ||
		HasTargetType(sp,EFF_TARGET_MINION)
		)
		return TTYPE_CASTER;
	return TTYPE_NULL;
}

ARCEMU_INLINE bool IsTargetingStealthed(SpellEntry *sp)
{
	if(
		HasTargetType(sp,EFF_TARGET_INVISIBLE_OR_HIDDEN_ENEMIES_AT_LOCATION_RADIUS) ||
		HasTargetType(sp,EFF_TARGET_ALL_ENEMIES_AROUND_CASTER) ||
		HasTargetType(sp,EFF_TARGET_ALL_ENEMY_IN_AREA_CHANNELED) ||
		HasTargetType(sp,EFF_TARGET_ALL_ENEMY_IN_AREA_INSTANT)
		)
		return 1;

	if(
		sp->NameHash == SPELL_HASH_MAGMA_TOTEM
		)
		return 1;

	return 0;
}

// slow
struct SpellTargetMod
{
    SpellTargetMod(uint64 _TargetGuid, uint8 _TargetModType) : TargetGuid(_TargetGuid), TargetModType(_TargetModType)
    {

    }
    uint64 TargetGuid;
    uint8  TargetModType;
};


typedef std::vector<SpellTargetMod> SpellTargetsList;

typedef void(Spell::*pSpellEffect)(uint32 i);
typedef void(Spell::*pSpellTarget)(uint32 i, uint32 j);

#define POWER_TYPE_HEALTH -2
#define POWER_TYPE_MANA 0
#define POWER_TYPE_RAGE 1
#define POWER_TYPE_FOCUS 2
#define POWER_TYPE_ENERGY 3
#define POWER_TYPE_HAPPINESS 4
#define POWER_TYPE_RUNES 5
// we have power type 15 and 31 :S

#define GO_FISHING_BOBBER 35591

#define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL 1000
class DummySpellHandler;

enum SpellDidHitResult
{
	SPELL_DID_HIT_SUCCESS					= 0,
	SPELL_DID_HIT_MISS						= 1,
	SPELL_DID_HIT_RESIST					= 2,
	SPELL_DID_HIT_DODGE						= 3,
	SPELL_DID_HIT_DEFLECT					= 4,
	SPELL_DID_HIT_BLOCK						= 5,
	SPELL_DID_HIT_EVADE						= 6,
	SPELL_DID_HIT_IMMUNE					= 7,
};

// Spell instance
class SERVER_DECL Spell
{
public:
    friend class DummySpellHandler;
    Spell( );
	void Init( Object* Caster, SpellEntry *info, bool triggered, Aura* aur );
	void Virtual_Constructor();		//when using object pool contructor is not good to be called again sometimes. Use this instead
    ~Spell();
	void Virtual_Destructor();		//this makes sure we do not leave events on objects that are supposed to be deleted
	int32 m_bufferPoolId;

    // Fills specified targets at the area of effect
    void FillSpecifiedTargetsInArea(float srcx,float srcy,float srcz,uint32 ind, uint32 specification);
    // Fills specified targets at the area of effect. We suppose we already inited this spell and know the details
    void FillSpecifiedTargetsInArea(uint32 i,float srcx,float srcy,float srcz, float range, uint32 specification);
    // Fills the targets at the area of effect
    void FillAllTargetsInArea(uint32 i, float srcx,float srcy,float srcz, float range);
    // Fills the targets at the area of effect. We suppose we already inited this spell and know the details
    void FillAllTargetsInArea(float srcx,float srcy,float srcz,uint32 ind);
    // Fills the targets at the area of effect. We suppose we already inited this spell and know the details
    void FillAllTargetsInArea(LocationVector & location,uint32 ind);
    // Fills the targets at the area of effect. We suppose we already inited this spell and know the details
    void FillAllFriendlyInArea(uint32 i, float srcx,float srcy,float srcz, float range);
    //get single Enemy as target
    uint64 GetSinglePossibleEnemy(uint32 i, float prange=0);
    //get single Enemy as target
    uint64 GetSinglePossibleFriend(uint32 i, float prange=0);
    //generate possible target list for a spell. Use as last resort since it is not acurate
    void GenerateTargets(SpellCastTargets *store_buff);
    // Fills the target map of the spell packet
    void FillTargetMap(uint32);
    // See if we hit the target or can it resist (evade/immune/resist on spellgo) (0=success)
    uint8 DidHit(uint32 effindex,Unit* target);
    // Prepares the spell thats going to cast to targets
    uint8 prepare(SpellCastTargets * targets);
    // Cancels the current spell
    void cancel();
    // Update spell state based on time difference
    void update(uint32 difftime);
    // Casts the spell
    void cast(bool);
    // Finishes the casted spell
    void finish();
    // Handle the Effects of the Spell
    void HandleEffects(uint64 guid,uint32 i);
    // Take Power from the caster based on spell power usage
    bool TakePower();
    // Has power?
    bool HasPower();
    // Trigger Spell function that triggers triggered spells
    void TriggerSpell();
    // Checks the caster is ready for cast
    uint8 CanCast(bool);
    // Removes reagents, ammo, and items/charges
    void RemoveItems();
    // Calculates the i'th effect value
    int32 CalculateEffect(uint32, Unit *target);
    // Handles Teleport function
    void HandleTeleport(uint32 id, Unit* Target);
    // Determines how much skill caster going to gain
    void DetermineSkillUp();
    // Increases cast time of the spell
    void AddTime(uint32 type);
    void AddCooldown();
    void AddStartCooldown();


    bool Reflect(Unit * refunit);

    ARCEMU_INLINE uint32 getState() { return m_spellState; }
    ARCEMU_INLINE void SetUnitTarget(Unit *punit){unitTarget=punit;}

    // Send Packet functions
    void SendCastResult(uint8 result);
    void SendSpellStart();
    void SendSpellGo();
    void SendLogExecute(uint32 damage, uint64 & targetGuid);
    void SendInterrupted(uint8 result);
    void SendChannelUpdate(uint32 time);
    void SendChannelStart(uint32 duration);
    void SendResurrectRequest(Player* target);
    void SendHealSpellOnPlayer(Object* caster, Object* target, uint32 dmg,bool critical);
	void SendHealManaSpellOnPlayer(Object * caster, Object * target, uint32 dmg, uint32 powertype);
	void SendTameFailure( uint8 failure );
    

    void HandleAddAura(uint64 guid);
    void writeSpellGoTargets( WorldPacket * data );
    void writeSpellMissedTargets( WorldPacket * data );

    uint32 pSpellId;
    SpellEntry *ProcedOnSpell; //some spells need to know the origins of the proc too
    SpellCastTargets m_targets;

    void CreateItem(uint32 itemId);

    // Effect Handlers
    void SpellEffectNULL(uint32 i);
    void SpellEffectInstantKill(uint32 i);
    void SpellEffectSchoolDMG(uint32 i);
    void SpellEffectDummy(uint32 i);
	void SpellEffectRestoreManaPct(uint32 i);
    void SpellEffectTeleportUnits(uint32 i);
    void SpellEffectApplyAura(uint32 i);
    void SpellEffectPowerDrain(uint32 i);
    void SpellEffectHealthLeech(uint32 i);
    void SpellEffectHeal(uint32 i);
    void SpellEffectQuestComplete(uint32 i);
    void SpellEffectWeapondamageNoschool(uint32 i);
    void SpellEffectResurrect(uint32 i);
    void SpellEffectAddExtraAttacks(uint32 i);
    void SpellEffectDodge(uint32 i);
    void SpellEffectBlock(uint32 i);
    void SpellEffectParry(uint32 i);
    void SpellEffectCreateItem(uint32 i);
    void SpellEffectPersistentAA(uint32 i);
    void SpellEffectSummon(uint32 i);
    void SpellEffectLeap(uint32 i);
    void SpellEffectEnergize(uint32 i);
    void SpellEffectWeaponDmgPerc(uint32 i);
    void SpellEffectTriggerMissile(uint32 i);
    void SpellEffectOpenLock(uint32 i);
    void SpellEffectApplyAA(uint32 i);
    void SpellEffectLearnSpell(uint32 i);
    void SpellEffectSpellDefense(uint32 i);
    void SpellEffectDispel(uint32 i);
    void SpellEffectSummonWild(uint32 i);
    void SpellEffectSummonGuardian(uint32 i);
    void SpellEffectSkillStep(uint32 i);
    void SpellEffectSummonObject(uint32 i);
    void SpellEffectEnchantItem(uint32 i);
    void SpellEffectEnchantItemTemporary(uint32 i);
    void SpellEffectTameCreature(uint32 i);
    void SpellEffectSummonPet(uint32 i);
    void SpellEffectWeapondamage(uint32 i);
    void SpellEffectPowerBurn(uint32 i);
    void SpellEffectThreat(uint32 i);
    void SpellEffectTriggerSpell(uint32 i);
    void SpellEffectHealthFunnel(uint32 i);
    void SpellEffectPowerFunnel(uint32 i);
    void SpellEffectHealMaxHealth(uint32 i);
    void SpellEffectInterruptCast(uint32 i);
    void SpellEffectDistract(uint32 i);
    void SpellEffectPickpocket(uint32 i);
    void SpellEffectAddFarsight(uint32 i);
    void SpellEffectSummonPossessed(uint32 i);
	void SpellEffectUseGlyph(uint32 i);
    void SpellEffectCreateSummonTotem(uint32 i);
    void SpellEffectHealMechanical(uint32 i);
    void SpellEffectSummonObjectWild(uint32 i);
    void SpellEffectScriptEffect(uint32 i);
    void SpellEffectSanctuary(uint32 i);
    void SpellEffectAddComboPoints(uint32 i);
	void SpellEffectCreateHouse(uint32 i);
    void SpellEffectDuel(uint32 i);
    void SpellEffectStuck(uint32 i);
    void SpellEffectSummonPlayer(uint32 i);
    void SpellEffectActivateObject(uint32 i);
    void SpellEffectSummonTotem(uint32 i);
    void SpellEffectProficiency(uint32 i);
    void SpellEffectSendEvent(uint32 i);
    void SpellEffectSkinning(uint32 i);
    void SpellEffectCharge(uint32 i);
    void SpellEffectSummonCritter(uint32 i);
    void SpellEffectKnockBack(uint32 i);
    void SpellEffectInebriate(uint32 i);
    void SpellEffectFeedPet(uint32 i);
    void SpellEffectDismissPet(uint32 i);
    void SpellEffectReputation(uint32 i);
    void SpellEffectSummonObjectSlot(uint32 i);
    void SpellEffectDispelMechanic(uint32 i);
    void SpellEffectSummonDeadPet(uint32 i);
    void SpellEffectDestroyAllTotems(uint32 i);
    void SpellEffectSummonDemon(uint32 i);
    void SpellEffectAttackMe(uint32 i);
    void SpellEffectSkill(uint32 i);
    void SpellEffectApplyPetAura(uint32 i);
    void SpellEffectDummyMelee(uint32 i);
	void SpellEffectFilming(uint32 i);
    void SpellEffectPlayerPull( uint32 i );
    void SpellEffectSpellSteal(uint32 i);
    void SpellEffectProspecting(uint32 i);
    void SpellEffectOpenLockItem(uint32 i);
    void SpellEffectSelfResurrect(uint32 i);
    void SpellEffectDisenchant(uint32 i);
    void SpellEffectWeapon(uint32 i);
    void SpellEffectDefense(uint32 i);
    void SpellEffectDualWield(uint32 i);
    void SpellEffectSkinPlayerCorpse(uint32 i);
    void SpellEffectResurrectNew(uint32 i);
    void SpellEffectTranformItem(uint32);
    void SpellEffectEnvironmentalDamage(uint32);
    void SpellEffectLearnPetSpell(uint32 i);
    void SpellEffectEnchantHeldItem(uint32 i);
    void SpellEffectAddHonor(uint32 i);
    void SpellEffectSpawn(uint32 i);
    void SpellEffectApplyAura128(uint32 i);
    void SpellEffectTriggerSpellWithValue(uint32 i);
    void SpellEffectSummonTarget(uint32 i);
	void SpellEffectForgetSpecialization(uint32 i);
	void SpellEffectRedirectThreat(uint32 i);
	void SpellEffectReduceThreatPercent(uint32 i);

    // Spell Targets Handlers
    void SpellTargetNULL(uint32 i, uint32 j);
    void SpellTargetDefault(uint32 i, uint32 j);
    void SpellTargetSelf(uint32 i, uint32 j);
    void SpellTargetInvisibleAOE(uint32 i, uint32 j);
    void SpellTargetFriendly(uint32 i, uint32 j);
    void SpellTargetPet(uint32 i, uint32 j);
    void SpellTargetSingleTargetEnemy(uint32 i, uint32 j);
    void SpellTargetCustomAreaOfEffect(uint32 i, uint32 j);
    void SpellTargetAreaOfEffect(uint32 i, uint32 j);
    void SpellTargetLandUnderCaster(uint32 i, uint32 j); /// I don't think this is the correct name for this one
    void SpellTargetAllPartyMembersRangeNR(uint32 i, uint32 j);
    void SpellTargetSingleTargetFriend(uint32 i, uint32 j);
    void SpellTargetAoE(uint32 i, uint32 j); // something special
    void SpellTargetSingleGameobjectTarget(uint32 i, uint32 j);
    void SpellTargetInFrontOfCaster(uint32 i, uint32 j);
    void SpellTargetSingleFriend(uint32 i, uint32 j);
    void SpellTargetGameobject_itemTarget(uint32 i, uint32 j);
    void SpellTargetPetOwner(uint32 i, uint32 j);
    void SpellTargetEnemysAreaOfEffect(uint32 i, uint32 j);
    void SpellTargetTypeTAOE(uint32 i, uint32 j);
    void SpellTargetAllyBasedAreaEffect(uint32 i, uint32 j);
    void SpellTargetScriptedEffects(uint32 i, uint32 j);
    void SpellTargetSummon(uint32 i, uint32 j);
    void SpellTargetNearbyPartyMembers(uint32 i, uint32 j);
    void SpellTargetSingleTargetPartyMember(uint32 i, uint32 j);
    void SpellTargetScriptedEffects2(uint32 i, uint32 j);
    void SpellTargetPartyMember(uint32 i, uint32 j);
    void SpellTargetDummyTarget(uint32 i, uint32 j);
    void SpellTargetFishing(uint32 i, uint32 j);
    void SpellTargetType40(uint32 i, uint32 j);
    void SpellTargetTotem(uint32 i, uint32 j);
    void SpellTargetChainTargeting(uint32 i, uint32 j);
    void SpellTargetSimpleTargetAdd(uint32 i, uint32 j);
    void SpellTarget56(uint32 o, uint32 j);
    void SpellTargetTargetAreaSelectedUnit(uint32 i, uint32 j);
    void SpellTargetInFrontOfCaster2(uint32 i, uint32 j);
    void SpellTargetTargetPartyMember(uint32 i, uint32 j);
    void SpellTargetSameGroupSameClass(uint32 i, uint32 j);
	//these are custom
    void SpellTargetSinglePartyInjured(uint32 i, uint32 j);
    void SpellTargetMultiplePartyInjured(uint32 i, uint32 j);

    void Heal(int32 amount, bool ForceCrit = false);

    GameObject*		g_caster;
    Unit*			u_caster;
    Item*			i_caster;
    Player*			p_caster;
    Object*			m_caster;

    // 15007 = resurecting sickness
	
	// This returns SPELL_ENTRY_Spell_Dmg_Type where 0 = SPELL_DMG_TYPE_NONE, 1 = SPELL_DMG_TYPE_MAGIC, 2 = SPELL_DMG_TYPE_MELEE, 3 = SPELL_DMG_TYPE_RANGED
	// It should NOT be used for weapon_damage_type which needs: 0 = MELEE, 1 = OFFHAND, 2 = RANGED
	ARCEMU_INLINE uint32 GetType() { return ( GetProto()->Spell_Dmg_Type == SPELL_DMG_TYPE_NONE ? SPELL_DMG_TYPE_MAGIC : GetProto()->Spell_Dmg_Type ); }

	map_t UniqueTargets;
    SpellTargetsList    ModeratedTargets;

    ARCEMU_INLINE Item* GetItemTarget() { return itemTarget; }
    ARCEMU_INLINE Unit* GetUnitTarget() { return unitTarget; }
    ARCEMU_INLINE Player* GetPlayerTarget() { return playerTarget; }
    ARCEMU_INLINE GameObject* GetGameObjectTarget() { return gameObjTarget; }

    uint32 chaindamage;
    // -------------------------------------------

    bool IsAspect();
    bool IsSeal();

	ARCEMU_INLINE SpellEntry* GetProto() { return (m_spellInfo_override == NULL) ?  m_spellInfo : m_spellInfo_override; }
	void InitProtoOverride()
	{
		if (m_spellInfo_override != NULL)
			return;
		m_spellInfo_override = dbcSpell.CreateCopy(m_spellInfo);
	}
    uint32 GetDuration()
    {
        if(bDurSet)return Dur;
        bDurSet=true;
        int32 c_dur = 0;

        if(GetProto()->DurationIndex)
        {
            SpellDuration *sd=dbcSpellDuration.LookupEntry(GetProto()->DurationIndex);
            if(sd)
            {
                //check for negative and 0 durations.
                //duration affected by level
                if((int32)sd->Duration1 < 0 && sd->Duration2 && u_caster)
                {
                    this->Dur = uint32(((int32)sd->Duration1 + (sd->Duration2 * u_caster->getLevel())));
                    if((int32)this->Dur > 0 && sd->Duration3 > 0 && (int32)this->Dur > (int32)sd->Duration3)
                    {
                        this->Dur = sd->Duration3;
                    }

                    if((int32)this->Dur < 0)
						this->Dur = 0;
					c_dur = this->Dur;
                }
                if(sd->Duration1 >= 0 && !c_dur)
                {
                    this->Dur = sd->Duration1;
                }
                //combo point lolerCopter? ;P
                if(p_caster)  
                {
                    uint32 cp=p_caster->m_comboPoints;
                    if(cp)
                    {
                        uint32 bonus=(cp*(sd->Duration3-sd->Duration1))/5;
                        if(bonus)
                        {
                            this->Dur+=bonus;
                            m_requiresCP=true;
                        }
                    }
                }

                if(GetProto()->SpellGroupType && u_caster)
                {
                    SM_FIValue(u_caster->SM_FDur,(int32*)&this->Dur,GetProto()->SpellGroupType);
                    SM_PIValue(u_caster->SM_PDur,(int32*)&this->Dur,GetProto()->SpellGroupType);
#ifdef COLLECTION_OF_UNTESTED_STUFF_AND_TESTERS
					int spell_flat_modifers=0;
					int spell_pct_modifers=0;
					SM_FIValue(u_caster->SM_FDur,&spell_flat_modifers,GetProto()->SpellGroupType);
					SM_FIValue(u_caster->SM_PDur,&spell_pct_modifers,GetProto()->SpellGroupType);
					if(spell_flat_modifers!=0 || spell_pct_modifers!=0)
						printf("!!!!!spell duration mod flat %d , spell duration mod pct %d , spell duration %d, spell group %u\n",spell_flat_modifers,spell_pct_modifers,Dur,GetProto()->SpellGroupType);
#endif
                }
            }
            else
            {
                this->Dur = (uint32)-1;
            }
        }
        else
        {
             this->Dur = (uint32)-1;
        }

        return this->Dur;
    }

    ARCEMU_INLINE float GetRadius(uint32 i)
    {
        if(bRadSet[i])return Rad[i];
        bRadSet[i]=true;
        Rad[i]=::GetRadius(dbcSpellRadius.LookupEntry(GetProto()->EffectRadiusIndex[i]));
		if(GetProto()->SpellGroupType && u_caster)
        {
            SM_FFValue(u_caster->SM_FRadius,&Rad[i],GetProto()->SpellGroupType);
            SM_PFValue(u_caster->SM_PRadius,&Rad[i],GetProto()->SpellGroupType);
#ifdef COLLECTION_OF_UNTESTED_STUFF_AND_TESTERS
			float spell_flat_modifers=0;
			float spell_pct_modifers=1;
			SM_FFValue(u_caster->SM_FRadius,&spell_flat_modifers,GetProto()->SpellGroupType);
			SM_PFValue(u_caster->SM_PRadius,&spell_pct_modifers,GetProto()->SpellGroupType);
			if(spell_flat_modifers!=0 || spell_pct_modifers!=1)
				printf("!!!!!spell radius mod flat %f , spell radius mod pct %f , spell radius %f, spell group %u\n",spell_flat_modifers,spell_pct_modifers,Rad[i],GetProto()->SpellGroupType);
#endif
        }

        return Rad[i];
    }

    ARCEMU_INLINE static uint32 GetBaseThreat(uint32 dmg)
    {
        //there should be a formula to determine what spell cause threat and which don't
/*        switch(GetProto()->NameHash)
        {
            //hunter's mark
            case 4287212498:
                {
                    return 0;
                }break;
        }*/
        return dmg;
    }
    bool IsStealthSpell();
    bool IsInvisibilitySpell();
    
    int32 damage;
    Aura* m_triggeredByAura;
	signed int	forced_basepoints[3]; //some talent inherit base points from previous caster spells

    bool m_triggeredSpell;
    bool m_AreaAura;
    //uint32 TriggerSpellId;  // used to set next spell to use
    //uint64 TriggerSpellTarget; // used to set next spell target
    bool m_requiresCP;
    float m_castPositionX;
    float m_castPositionY;
    float m_castPositionZ;
   
    int32 damageToHit;
    uint32 castedItemId;
    bool judgement;
	uint8 extra_cast_number;

    void SendCastSuccess(Object * target);
    void SendCastSuccess(const uint64& guid);

    bool duelSpell;

	ARCEMU_INLINE void safe_cancel()
	{
		m_cancelled = true;
	}

    /// Spell state's
    /// Spell failed
    ARCEMU_INLINE bool GetSpellFailed(){return m_Spell_Failed;}
    ARCEMU_INLINE void SetSpellFailed(bool failed = true){m_Spell_Failed = failed;}

    ARCEMU_INLINE bool IsReflected() {return m_IsReflected;}
    ARCEMU_INLINE void SetReflected(bool reflected = true) {m_IsReflected = reflected;}
    
    /// Spell possibility's
    ARCEMU_INLINE bool GetCanReflect() {return m_CanRelect;}
    ARCEMU_INLINE void SetCanReflect(bool reflect = true) {m_CanRelect = reflect;}


	Spell * m_reflectedParent;

protected:

    /// Spell state's
    bool    m_usesMana;
    bool    m_Spell_Failed;        //for 5sr
    bool    m_IsReflected;
    bool    m_Delayed;
    
    
    // Spell possibility's
    bool m_CanRelect;
    
    bool m_IsCastedOnSelf;

    bool hadEffect;

    uint32  m_spellState;
    int32   m_castTime;
    int32   m_timer;
	int64 m_magnetTarget;

    // Current Targets to be used in effect handler
    Unit*       unitTarget;
    Item*       itemTarget;
    GameObject* gameObjTarget;
    Player*     playerTarget;
    Corpse*     corpseTarget;
    uint32      add_damage;

    uint8       cancastresult;
    uint32      Dur;
    bool        bDurSet;
    float       Rad[3];
    bool        bRadSet[3];
	bool        m_cancelled;
	bool m_isCasting;
    //void _DamageRangeUpdate();

	ARCEMU_INLINE bool HasTarget(const uint64& guid, map_t* tmpMap)
	{
		for (int i=0; i<hashmap64_length(tmpMap); i++) {
			uint64 tguid;
			if (hashmap64_get_index(tmpMap, i, (int64*)&tguid, NULL) == MAP_OK) {
				if (tguid == guid)
					return true;
			}
		}

		for(SpellTargetsList::iterator itr = ModeratedTargets.begin(); itr != ModeratedTargets.end(); ++itr)
			if((*itr).TargetGuid==guid)
				return true;

		return false;
	}

private:
	map_t m_targetUnits[3];
    void SafeAddTarget(map_t tgt,uint64 guid);
    
    void SafeAddMissedTarget(uint64 guid);
    void SafeAddModeratedTarget(uint64 guid, uint16 type);

    friend class DynamicObject;
    void DetermineSkillUp(uint32 skillid,uint32 targetlevel);
    void DetermineSkillUp(uint32 skillid);

public:
	SpellEntry* m_spellInfo;
	SpellEntry* m_spellInfo_override;//used by spells that should have dynamic variables in spellentry.

};

void ApplyDiminishingReturnTimer(uint32 * Duration, Unit * Target, SpellEntry * spell);
void UnapplyDiminishingReturnTimer(Unit * Target, SpellEntry * spell);
uint32 GetDiminishingGroup(uint32 NameHash);

#endif
